package com.teamtgv.shareshark.location;

import java.io.IOException;
import java.util.List;
import java.util.Locale;

import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;


public class LocationHelper {
	
	
	LocationManager locationManager; // location manager
	private Location foundLocation; // result
	boolean gpsEnabled = false;
	boolean networkEnabled = false;

	/**
	 * Retrieve the current location
	 * @param context
	 * 			The context from which the request arrives
	 * @param result
	 * 			The result
	 * @return
	 * 			result == current location (if possible)
	 */
	public String getLocation(Context context) {		
		locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
		
		// exceptions thrown if provider not enabled
		try {
			gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
		} catch (Exception ex) {
			return ex.getMessage();
		}
		
		try {
			networkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
		} catch (Exception ex) {
			return ex.getMessage();
		}

		// dont start listeners if no provider is enabled
		if (!gpsEnabled && !networkEnabled)
			return "no gps or network enabled";

		if (gpsEnabled)
			locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListenerGps);
		if (networkEnabled)
			locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListenerNetwork);

		getLastLocation();
		
		if (foundLocation == null)
			return "no location found";
		return determineAddress(context);
	}

	private LocationListener locationListenerGps = new LocationListener() {
		public void onLocationChanged(Location location) {
			foundLocation = location;
			locationManager.removeUpdates(this);
			locationManager.removeUpdates(locationListenerNetwork);
		}

		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extra) {
		}
	};

	private LocationListener locationListenerNetwork = new LocationListener() {
		public void onLocationChanged(Location location) {
			foundLocation = location;
			locationManager.removeUpdates(this);
			locationManager.removeUpdates(locationListenerGps);
		}

		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extra) {
		}

	};

	private void getLastLocation() {
		locationManager.removeUpdates(locationListenerGps);
		locationManager.removeUpdates(locationListenerNetwork);

		Location gpsLocation = null;
		Location networkLocation = null;

		if (gpsEnabled)
			gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		if (networkEnabled)
			networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

		// if there are both values use the latest one
		if (gpsLocation != null && networkLocation != null) {
			if (gpsLocation.getTime() > networkLocation.getTime())
				foundLocation = gpsLocation;
			else
				foundLocation = networkLocation;
			
			return;
		}

		if (gpsLocation != null)
			foundLocation = gpsLocation;

		if (networkLocation != null)
			foundLocation = networkLocation;

	}
	
	private String determineAddress(Context context) {
		if (foundLocation == null)
			return "";
		
		Geocoder geocoder = new Geocoder(context, Locale.getDefault());

		String address = "";
        List<Address> addresses = null;
        try {
            // Call the synchronous getFromLocation() method by passing in the lat/long values.
            addresses = geocoder.getFromLocation(foundLocation.getLatitude(), foundLocation.getLongitude(), 1);
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (addresses != null && addresses.size() > 0) {
            Address foundAddress = addresses.get(0);
            // Format the first line of address (if available), city, and country name.
            String street = foundAddress.getMaxAddressLineIndex() > 0 ? foundAddress.getAddressLine(0) : "";
            if (! street.equals("")) {
            	String[] streetParts = street.split(" ");
            	if (streetParts.length >= 2) {
            		street = "";
            		for (int i = 0; i < streetParts.length - 1; i++) 
            			street += streetParts[i];
            	}
            }
            address = String.format("%s, %s, %s", street,
            				foundAddress.getLocality(),
            				foundAddress.getCountryName());
        }
        return address;
	}
}